import React, { useContext, useEffect, useMemo, useState } from 'react';
import { Controller, useForm } from 'react-hook-form';

import { getIsAuth } from '@/entities/auth/model/selectors';
import { env, innerUrls, regex } from '@/shared/constants';
import { ModalContext } from '@/shared/context/ModalContext';
import { ReactComponent as PromoIcon } from '@/shared/icons/icon-promo.svg';
import { Modals } from '@/shared/interfaces';
import { OrderCountPriceResponseDto } from '@/shared/interfaces/generated';
import { isFetchBaseQueryErrorType } from '@/shared/interfaces/typeCheckers';
import { validateEmail } from '@/shared/lib';
import { useKeyboard } from '@/shared/lib/hooks';
import { useAppSelector } from '@/shared/store';
import { Banner, Button, ButtonVariants, FlexWrapper, Input, Loader, SecondInput, Snackbar } from '@/shared/ui';
import { ModalPage } from '@/widgets/ModalPage';
import { yupResolver } from '@hookform/resolvers/yup';
import cn from 'classnames';
import { useSnackbar } from 'notistack';
import { useDebounceValue, useWindowSize } from 'usehooks-ts';
import * as yup from 'yup';

import { productApi, SmallCourseCard, SmallCourseCardLoader } from '../..';
import cs from './CreateOrderModal.module.scss';

const schema = yup.object().shape({
  phone: yup.string().matches(regex.phone).required(),
  promo: yup
    .string()
    .transform((value) => value.toUpperCase())
    .uppercase()
    .matches(regex.promo),
});

const discountType = {
  ruble: ' ₽', // note: пробел в начале не миссклик
  percentage: '%',
} satisfies Record<OrderCountPriceResponseDto['discountCurrency'], string>;

const errorMessages = {
  'Promocode expired': 'Промокод недействителен',
  'Promocode not found': 'Промокод не найден',
};
export const CreateOrderModal = () => {
  const isAuth = useAppSelector(getIsAuth);
  const emailFromLocalStorage = localStorage.getItem('authEmail');

  const [isPromoOpen, setIsPromoOpen] = useState(false);
  const [isCorrectEmail, setIsCorrectEmail] = useState<boolean>(true); // валидация емаила
  const [isCorrectEmailShown, setIsCorrectEmailShown] = useState<boolean>(false);
  const [email, setEmail] = useState('');

  const { openModal, closeModal, data, setData } = useContext(ModalContext);
  const { enqueueSnackbar } = useSnackbar();
  const { width } = useWindowSize();
  const {
    register,
    handleSubmit,
    formState: { errors, dirtyFields, isValid },
    resetField,
    watch,
    clearErrors,
    reset,
    control,
  } = useForm({
    reValidateMode: 'onChange',
    mode: 'onBlur',
    resolver: yupResolver(schema),
    shouldFocusError: false,
    defaultValues: {
      phone: '',
      promo: '',
    },
  });

  const { data: course, isLoading, error } = productApi.useGetSingleProductQuery(data.id);
  const [countPrice, { data: promocode, isLoading: isPromoLoading, error: promoError }] =
    productApi.useGetOrderPriceMutation();
  const [createOrder] = productApi.useCreateOrderMutation();
  const [orderFreeProduct] = productApi.useOrderFreeProductMutation();
  const [promo, setPromo] = useDebounceValue(watch('promo'), 600);
  useEffect(() => {
    setPromo(watch('promo').toUpperCase());
  }, [watch('promo')]);
  useEffect(() => {
    if (!promo || !course?.product.id || !isAuth) {
      return;
    }
    countPrice({
      promocode: promo,
      productId: Number(course?.product.id),
    });
  }, [promo]);
  const onSubmit = handleSubmit((formData) => {
    if (!isValid) {
      return;
    }
    const isPrice =
      (Number(course?.product.discountPrice) && Number(course?.product.discountPrice) > 0) ||
      (course?.product.discountPrice === null && Number(course?.product.price) > 0);
    const widget = isPrice ? window.open() : null;
    createOrder({
      name: 'Имя не указано',
      phone: formData.phone.replace(/ /g, ''),
      email,
      productId: Number(course?.product.id),
      promocode: isAuth ? promo : '',
    })
      .unwrap()
      .then((res) => {
        setData(() => ({ ...data, email, courseName: course?.product.title }));
        if (isPrice) {
          closeModal();
          if (!widget) return;
          widget.location = `${env.apiUrl}/payment-widget/tinkoff?orderId=${res.id}`;
          // window.open(`${API_URL}/payment-widget/tinkoff?orderId=${res.id}`, '_self');
        } else {
          orderFreeProduct({ orderId: res.id });
          openModal(Modals.SuccessModal);
        }

        reset();
      })
      .catch((e) => {
        closeModal();
        enqueueSnackbar(`Ошибка при создании заказа (${e.data.status as string}}`, {
          variant: 'error',
          content: (key, message) => <Snackbar id={key} message={message} size="md" variant="error" />,
        });
      });
  });

  const clearing = () => {
    clearErrors();
  };

  const handleSetEmail = (event: React.ChangeEvent<HTMLInputElement>) => {
    setIsCorrectEmailShown(false);
    const { value } = event.target;
    setEmail(value);
  };

  const handleClear = () => {
    setIsCorrectEmail(true);
    setEmail('');
  };

  useEffect(() => {
    if (!email.length) {
      return;
    }
    const isEmailValid = validateEmail(email);

    if (isEmailValid !== null) {
      setIsCorrectEmail(!!isEmailValid);
    } else {
      setIsCorrectEmail(false);
    }
  }, [email]);

  const isRequested = useMemo(
    () => (promocode || promoError) && watch('promo').trim() !== '' && promo.trim() !== '',
    [promocode, promoError, promo, watch('promo')],
  );

  const finalPrice = useMemo(
    () => (course?.product.discountPrice !== null ? course?.product.discountPrice : course?.product.price),
    [course],
  );

  const promoMessage = useMemo(() => {
    if (!promocode || finalPrice === undefined) {
      return '';
    }
    if (
      promocode?.discountCurrency === 'percentage' &&
      Math.round(finalPrice * (100 - promocode?.discount)) <= promocode?.price
    ) {
      return 'Применили максимальную скидку';
    }
    if (promocode?.discountCurrency === 'ruble' && finalPrice - promocode?.discount <= promocode?.price) {
      return 'Применили максимальную скидку';
    }
    return `Скидка ${promocode?.discount}
        ${discountType[promocode?.discountCurrency]}`;
  }, [promocode, finalPrice]);

  useEffect(() => {
    if (!emailFromLocalStorage) {
      return;
    }

    setEmail(() => emailFromLocalStorage);
  }, []);

  const handleOpenPromo = () => {
    if (isAuth) {
      setIsPromoOpen(true);
      return;
    }
    enqueueSnackbar(
      <>
        Необходима{' '}
        <Button href={innerUrls.auth.email} link target="_self" variant={ButtonVariants.Link}>
          авторизация
        </Button>
      </>,
      {
        variant: 'error',
        content: (key, message) => <Snackbar id={key} message={message} size="md" variant="error" />,
      },
    );
  };

  useKeyboard('Enter', onSubmit);
  return (
    <ModalPage className={cs.modal} handleClose={closeModal} isMobile={false} isOpen>
      <div className={cs.form}>
        <div className={cs.title_container}>
          <h1 className={cs.title}>Купить</h1>
        </div>
        {isLoading || !course ? (
          <SmallCourseCardLoader />
        ) : (
          <SmallCourseCard
            discountPrice={course?.product.discountPrice}
            image={course?.product.image}
            key={data.id}
            price={course?.product.price}
            title={course?.product.title}
          />
        )}
        <Banner>
          {course?.hasAttachments ? 'Отправим материал на почту' : 'Наш партнер свяжется с вами в течение суток'}
        </Banner>
        <FlexWrapper isModalWidth>
          <h6 className={cs.email}>Почта</h6>
          <Input
            data-testid="input-email"
            htmlFor="order"
            isAuthField
            isAutoFocus={!emailFromLocalStorage && width > 1024}
            isClose={email.length > 0}
            isEmailField
            isNotAccepted={isCorrectEmailShown && email.length !== 0}
            isNotAcceptedText="Некорректный формат"
            onBlur={() => {
              if (!isCorrectEmail) {
                setTimeout(() => {
                  setIsCorrectEmailShown(true);
                }, 100);
              }
            }}
            onChange={handleSetEmail}
            onClear={handleClear}
            value={email}
          />
        </FlexWrapper>
        <Controller
          control={control}
          name="phone"
          render={({ field }) => (
            <SecondInput
              autoFocus={!!emailFromLocalStorage && width > 768}
              className={cs.hide_placeholder}
              clearing={clearing}
              data-testid="phone-input"
              guide={false}
              inputMode="tel"
              isInvalid={!!errors['phone'] && !!dirtyFields['phone']}
              label="Телефон"
              mask={['+7', '', ' ', /[1-6]|[8-9]/, /\d/, /\d/, ' ', /\d/, /\d/, /\d/, ' ', /\d/, /\d/, ' ', /\d/, /\d/]}
              onRightClick={() => resetField('phone')}
              placeholder="+7"
              register={register}
              right={dirtyFields['phone'] ? 'clear' : null}
              {...field}
            />
          )}
        />

        {isPromoOpen ? (
          <SecondInput
            className={cs.promo_input}
            clearing={() => null}
            data-testid="input-promo"
            info={
              <div className={cs.promo_message}>
                {isRequested &&
                  !isPromoLoading &&
                  (promocode ? (
                    <span className={cs.active}>{promoMessage}</span>
                  ) : (
                    <span className={cs.expired}>
                      {(isFetchBaseQueryErrorType(promoError) &&
                        errorMessages?.[promoError?.data?.message as keyof typeof errorMessages]) ||
                        'Промокод недействителен'}
                    </span>
                  ))}
                {isPromoLoading && <Loader borderRadius={8} height={22} width={300} />}
              </div>
            }
            left={<PromoIcon className={cn(isRequested && !isPromoLoading && (promocode ? cs.active : cs.expired))} />}
            name="promo"
            onRightClick={() => resetField('promo')}
            placeholder="Промокод"
            register={register}
            right={dirtyFields['promo'] ? 'clear' : null}
            style={{ textTransform: watch('promo') ? 'uppercase' : undefined }}
          />
        ) : (
          <Button className={cn(cs.promo)} onClick={handleOpenPromo} variant={ButtonVariants.Link}>
            У меня есть промокод
          </Button>
        )}

        <div className={cs.buy_container}>
          <Button
            className={cn(cs.buy)}
            data-testid="buy-button"
            disabled={!!error || isLoading || !isValid || !isCorrectEmail || isPromoLoading || !email.length}
            onClick={onSubmit}
            variant={ButtonVariants.Primary}
          >
            {isLoading || course?.product.price === undefined ? (
              <Loader height={26} />
            ) : (
              <>
                Оплатить{' '}
                {promocode ? (
                  <>
                    {(promo.trim() ? Number(promocode?.price) : finalPrice || finalPrice)?.toLocaleString()}
                    &nbsp;₽&nbsp;
                    {!!promo.trim() && <span className={cs.discount_price}>{finalPrice}&nbsp;₽</span>}
                  </>
                ) : (
                  <>
                    {finalPrice?.toLocaleString()}
                    &nbsp;₽
                  </>
                )}
              </>
            )}
          </Button>

          <span className={cs.agreement}>
            Соглашаюсь с{' '}
            <Button className={cs.link} href={innerUrls.oferta} link target="_blank" variant={ButtonVariants.Link}>
              условиями
            </Button>{' '}
            и{' '}
            <Button className={cs.link} href={innerUrls.agreement} link target="_blank" variant={ButtonVariants.Link}>
              соглашением
            </Button>
          </span>
        </div>
      </div>
    </ModalPage>
  );
};
